package com.hnblc.blcwms.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hnblc.blcwms.common.constant.DictionaryConst;
import com.hnblc.blcwms.common.interaction.Response;
import com.hnblc.blcwms.persistent.business.odata.entity.OdataExpM;
import com.hnblc.blcwms.persistent.business.odata.service.IOdataExpMService;
import com.hnblc.blcwms.persistent.interfaces.business.entity.ExpLog;
import com.hnblc.blcwms.persistent.interfaces.business.entity.WmsRationnote;
import com.hnblc.blcwms.persistent.interfaces.business.service.IExpLogService;
import com.hnblc.blcwms.persistent.interfaces.business.service.IWmsRationnoteService;
import com.hnblc.blcwms.persistent.interfaces.client.entity.ClientAuth;
import com.hnblc.blcwms.persistent.interfaces.sysConfig.entity.FieldDictionary;
import com.hnblc.blcwms.persistent.interfaces.sysConfig.service.IFieldDictionaryService;
import com.hnblc.blcwms.serviceapi.api.dto.ration.cancel.ExpressCancel;
import com.hnblc.blcwms.serviceapi.api.dto.ration.note.ExpressBody;
import com.hnblc.blcwms.serviceapi.api.dto.ration.note.ExpressHead;
import com.hnblc.blcwms.serviceapi.api.enums.result.businiss.RationNoteResultEnum;
import com.hnblc.blcwms.serviceapi.api.service.IRationNoteAPIService;
import com.hnblc.blcwms.serviceapi.odata.IExpressService;
import com.hnblc.blcwms.serviceapi.odata.constant.ExpressConst;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Getter
@Setter
@Service
public class RationNoteAPIService implements IRationNoteAPIService {


    @Autowired
    IFieldDictionaryService fieldDictionaryService;

    @Autowired
    IExpressService expressService;

    @Autowired
    IOdataExpMService odataExpMService;

    @Autowired
    IWmsRationnoteService wmsRationnoteService;

    @Autowired
    IExpLogService expLogService;


    @Override
    public Response<Boolean> createRationNote(ExpressHead expressHead, ClientAuth clientAuth){
        //验证出货通知单是否已经存在并且待处理
        List<WmsRationnote> existNotes  =   this.wmsRationnoteService.list(new QueryWrapper<WmsRationnote>().eq("sheetid",expressHead.getSourceExpNo())
                .eq("shopid",clientAuth.getCustomNo()).eq("customid",clientAuth.getOwnerNo()));
        if (existNotes.size()>0)
            return new Response<>(RationNoteResultEnum.NOTE_ERROR_EXISTED);

        //判断出货类型是否正确
        String expressType = ExpressConst.EXP_TYPE_CODE_MAP.get(expressHead.getExpType());
        if(expressType==null){
            return new Response<>(RationNoteResultEnum.ERROR_UNKNOWN_TYPE);
        }/*else {
            expressHead.setExpType(expressType);
        }*/
        //合并相同内件数量，并生成出货通知单明细
        Map<String,WmsRationnote> rationNotes = new HashMap<>();
        Double allQty = 0.0;
        for (int i=0;i<expressHead.getOrderDetails().size();i++){
            ExpressBody expressBody = expressHead.getOrderDetails().get(i);
            if(rationNotes.containsKey(expressBody.getOwnerArticleNo())){

                allQty += expressBody.getPlanQty();
                //合并相同内件的数量
                rationNotes.get(expressBody.getOwnerArticleNo()).setPlanqty(rationNotes.get(expressBody.getOwnerArticleNo()).getPlanqty()+expressBody.getPlanQty());
            }else {
                allQty += expressBody.getPlanQty();
                WmsRationnote rationNote = this.buildNewRationNote(expressHead,expressBody,clientAuth);
                rationNote.setSerialid((double) (i + 1));
                rationNotes.put(expressBody.getOwnerArticleNo(),rationNote);
            }
        }
        //核对包裹详情SKU数量
        if (rationNotes.size()!=expressHead.getSkuCount())
            return new Response<>(RationNoteResultEnum.ERROR_SKU_COUNT);
        //核对包裹商品总数量
        if (expressHead.getGoodCount().doubleValue() != allQty.doubleValue())
            return new Response<>(RationNoteResultEnum.ERROR_GOOD_COUNT);

        if (!wmsRationnoteService.saveBatch(rationNotes.values())){
            return new Response<>(RationNoteResultEnum.ERROR_SAVE_FAIL);
        }else{
            return new Response<>(RationNoteResultEnum.SUCCESS);
        }
    }




    @Override
    public List<ExpressCancel> cancelOrders(ClientAuth clientAuth, List<ExpressCancel> orderCancelDtos, String messageId){
//        查出要取消的订单
        QueryWrapper<OdataExpM> queryWrapper = new QueryWrapper<>();
        // where cust_no ='12123' and ( order ='' or order='')
        queryWrapper.eq("enterprise_no",clientAuth.getEnterpriseNo())//客户编码
                .eq("warehouse_no",clientAuth.getWarehouseNo())
                .eq("owner_no",clientAuth.getOwnerNo())
                .eq("cust_no",clientAuth.getCustomNo())
                .and(i->{
                    for (ExpressCancel item : orderCancelDtos) {
                        i.or(wrapper -> wrapper.eq("SOURCEEXP_NO", item.getOrderNo()));
                    }
                    return i;
                });

        //查询订单信息
        List<OdataExpM> odataExpMs = odataExpMService.list(queryWrapper);

        //list转map
        Map<String, OdataExpM> ordersMap = odataExpMs.stream().collect(Collectors.toMap(OdataExpM::getSourceexpNo, Function.identity(),(key1, key2)->key2));



        List<ExpLog> errorList = new ArrayList<>();
        List<ExpLog> cancelList = new ArrayList<>();
        List<ExpressCancel> errorReturnList = new ArrayList<>();
        //出货单操作类型字典：10：创建订单；16：取消订单。此处为了和业务库状态值同步
        Map<String, FieldDictionary> operateType = fieldDictionaryService.mapLoadInCache("I_B_EXP_LOG","OPERATE_TYPE");
        //处理状态字典：1：操作成功，0：操作失败。
        Map<String, FieldDictionary> operateStatus = fieldDictionaryService.mapLoadInCache("I_B_EXP_LOG","STATUS");

        //错误状态代码字典：10：取消成功，11，未找到订单，12，状态异常，取消失败。
        Map<String, FieldDictionary> errorCode = fieldDictionaryService.mapLoadInCache("I_B_EXP_LOG","ERROR_CODE");


        orderCancelDtos.forEach(param -> {
            ExpLog item = new ExpLog();
            item.setOrderNo(param.getOrderNo());
            item.setOperateType(operateType.get(DictionaryConst.EXP_LOG__OPERATE_TYPE__CANCEL).getColumnValue());
            item.setMessageSeq(messageId);
            item.setOperateDate(LocalDateTime.now());
            item.setOperateClient(clientAuth.getClientId());

            OdataExpM expM = ordersMap.get(item.getOrderNo());
            if (expM == null){//未找到订单
                FieldDictionary errorObj = errorCode.get(DictionaryConst.EXP_LOG__ERROR_CODE__NOT_FOUND);
                //构造操作记录
                item.setStatus(operateStatus.get(DictionaryConst.EXP_LOG__STATUS__FAIL).getColumnValue());
                item.setErrorCode(errorObj.getColumnValue());
                errorList.add(item);
                //构造返回结果
                param.setOperateStatus(errorObj.getColumnValue());
                param.setCancelResult(errorObj.getColumnTextCn());
                errorReturnList.add(param);
            }else{
                if (!ExpressConst.ODATA_EXP_M__STATUS__READY.equals(expM.getStatus())){ //状态为不可自助取消状态
                    FieldDictionary errorObj;
                    if(ExpressConst.ODATA_EXP_M__STATUS__SEND.equalsIgnoreCase(expM.getStatus())){
                        errorObj = errorCode.get(DictionaryConst.EXP_LOG__ERROR_CODE__SEND);
                    }else{
                        errorObj = errorCode.get(DictionaryConst.EXP_LOG__ERROR_CODE__WRONG_STATUS);
                    }
                    item.setStatus(operateStatus.get(DictionaryConst.EXP_LOG__STATUS__FAIL).getColumnValue()); //操作失败
                    item.setErrorCode(errorObj.getColumnValue());  //失败原因
                    errorList.add(item);
                    //构造失败返回
                    param.setOperateStatus(errorObj.getColumnValue());
                    param.setCancelResult(errorObj.getColumnTextCn());
                    errorReturnList.add(param);
                }else{
                    if (expressService.cancelExpress(expM)) {
                        item.setStatus(operateStatus.get(DictionaryConst.EXP_LOG__STATUS__SUCCESS).getColumnValue()); //操作成功
                        cancelList.add(item);
                    }else{
                        FieldDictionary errorObj = errorCode.get(DictionaryConst.EXP_LOG__ERROR_CODE__WRONG_STATUS);
                        item.setStatus(operateStatus.get(DictionaryConst.EXP_LOG__STATUS__FAIL).getColumnValue()); //操作失败
                        item.setErrorCode(errorObj.getColumnValue());//不可取消状态
                        errorList.add(item);
                        param.setOperateStatus(errorObj.getColumnValue());
                        param.setCancelResult(errorObj.getColumnTextCn());
                        errorReturnList.add(param);
                    }
                }
            }
        });
        cancelList.addAll(errorList);
        expLogService.saveBatch(cancelList);
        return errorReturnList;
    }



    private WmsRationnote buildNewRationNote(ExpressHead expressHead, ExpressBody expressBody, ClientAuth clientAuth){

        //初始化内件信息
        WmsRationnote wmsRationnote = new WmsRationnote();
        wmsRationnote.setGoodsid(expressBody.getOwnerArticleNo());
        wmsRationnote.setBarcode(expressBody.getBarcode());
        wmsRationnote.setArticleIdentifier(expressBody.getArticleIdentifier());
        wmsRationnote.setPlanqty(expressBody.getPlanQty());
        wmsRationnote.setOrderunit("N");
        wmsRationnote.setOrderquantity(expressBody.getPlanQty());
        wmsRationnote.setUnitrate(0.00);
        wmsRationnote.setPkcount(expressBody.getPackingQty());
        wmsRationnote.setCost(expressBody.getUnitCost());
        wmsRationnote.setItemType(expressBody.getItemType());
        //初始化订单主体信息
        wmsRationnote.setSheetid(expressHead.getSourceExpNo());
        wmsRationnote.setRtype(new Double(expressHead.getExpType()).doubleValue());
        wmsRationnote.setCustomid(clientAuth.getOwnerNo());
        wmsRationnote.setPalletzone(clientAuth.getWarehouseNo());
        wmsRationnote.setType(expressHead.getFastFlag());
        wmsRationnote.setShopid(clientAuth.getCustomNo());
        wmsRationnote.setShopNo("A0000L");
        wmsRationnote.setRefsheetid(expressHead.getMailPoNo());//原订单号码（直通时，为进货单单号） ?
        wmsRationnote.setLeveltype("100");//配量优先级(1-999)默认值”100”’
        wmsRationnote.setSdate(LocalDateTime.now());
        //单内需要外层赋值
        wmsRationnote.setNotes(expressHead.getExpRemark());
        wmsRationnote.setShopNo(clientAuth.getCustomNo());
        wmsRationnote.setJhType(expressHead.getMailIeType());
        wmsRationnote.setShipperNo(expressHead.getLogisticNo());
        wmsRationnote.setShipperDeliverNo(expressHead.getLogisticWaybillNo());
        wmsRationnote.setOrderSource(expressHead.getOrderSource());
        wmsRationnote.setRsvVarod3(expressHead.getCustomsInspection());
        wmsRationnote.setSendAddress(expressHead.getShipperAddress());
        wmsRationnote.setSendName(expressHead.getShipper());
        wmsRationnote.setSendCompanyName(expressHead.getShipperCompanyName());
        wmsRationnote.setSendPostcode(expressHead.getShipperPostcode());
        wmsRationnote.setSendMobilePhone(expressHead.getShipperMobilePhone());
        wmsRationnote.setSendTelephone(expressHead.getShipperPhoneNo());
        wmsRationnote.setSendProvince(expressHead.getShipperProvince());
        wmsRationnote.setSendCity(expressHead.getShipperCity());
        wmsRationnote.setSendZone(expressHead.getShipperZone());
        wmsRationnote.setSendCountry(expressHead.getShipperStreet());
        wmsRationnote.setCustAddress(expressHead.getReceiverAddress());
        wmsRationnote.setContactorName(expressHead.getReceiver());
        wmsRationnote.setCustPhone(expressHead.getReceiverMobileNo());
        wmsRationnote.setCustMail(expressHead.getReceiverEMail());
        wmsRationnote.setReceiveProvince(expressHead.getReceiverProvince());
        wmsRationnote.setReceiveCity(expressHead.getReceiverCity());
        wmsRationnote.setReceiveZone(expressHead.getReceiverZone());
        wmsRationnote.setReceiveCountry(expressHead.getReceiverStreet());
        wmsRationnote.setStatus(expressHead.getOperate());
        wmsRationnote.setZtFlag(expressHead.getTakeType());
        wmsRationnote.setOrderBatch(expressHead.getOrderBatch());
        wmsRationnote.setDeliverAddress(expressHead.getDeliverAddress());
        return wmsRationnote;
    }

}
